#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Copyright © 启明星辰 版权所有
# @Time    : 2023/12/14 17:29
# @Author  : 胡浩浩
# @File    : case_convert.py
# @IDE     : PyCharm
# @description :
import json
import re
import time
from urllib.parse import unquote

from ruamel import yaml
from pywebio.output import *
from pywebio.pin import put_textarea, pin, pin_update
from pywebio.session import download

from frontend.menus import show_menus

title_style = """
color: red;
"""


class CaseConvert:
    """
        用例转化工具类,将curl请求转化为json格式的测试用例
    """

    def __init__(self, curl_data):
        self.curl_data = curl_data

    @staticmethod
    def handle_curl_2_yaml_case(curl_result):
        url_re = re.compile("'(http.{0,}://.*)'")
        url_result = re.search(url_re, curl_result).group()
        print(url_result)
        host_re = re.compile("(http.{0,}://.*?)/")
        host_result = re.findall(host_re, url_result)[0]
        print(host_result)
        path_re = re.compile(r"//.*?(/.*)'")
        path_result = re.findall(path_re, url_result)[0]
        print(path_result)
        params = {}
        if "?" in path_result:
            path_result, params_str = path_result.split("?")
            params_re = re.compile(r"([^=&]+)=([^&]*)")
            print(params_str)
            params_result = re.findall(params_re, params_str)
            print(params_result)
            for p in params_result:
                params[p[0]] = p[1]
            print(params)

        # 处理host,将铭文host替换成模板字符串
        curl_result = curl_result.replace(host_result, "${host}$")

        # ----------path参数---------------
        step_name = path_result.replace("/", "_")
        # ----------method参数---------------
        method_re_expression = re.compile("-X '(.*?)'", re.S)
        method_result_list = re.findall(method_re_expression, curl_result)
        method = None
        if method_result_list:
            method = method_result_list[0]

        headers = {}
        header_re_expression = re.compile("-H '(.*?): (.*?)'", re.S)
        header_result_list = re.findall(header_re_expression, curl_result)
        print(header_result_list)
        if header_result_list:
            for item in header_result_list:
                headers[item[0]] = item[1]
        print(headers)
        # 多余的headers参数处理
        if headers.get("Authorization"):
            del headers["Authorization"]
        if headers.get("Cookie"):
            del headers["Cookie"]
        if not method and headers.get("Content-Type") and "application/json" in headers.get("Content-Type"):
            method = "post"
        if not method and headers.get("Content-Type") and "application/x-www-form-urlencoded" in headers.get(
                "Content-Type"):
            method = "post"
        if not method:
            method = "get"
        # ----------data参数---------------
        data = {}
        if "--data-raw $'" in curl_result:
            data_re_expression = re.compile("--data-raw \$'(.*?)'", re.S)
            data_result_list = re.findall(data_re_expression, curl_result)
            print(data_result_list[0])
            if "WebKitFormBoundaryVn306igBdhrJQ9jO" in data_result_list[0]:
                # 按照指定分隔符进行分割
                pattern = r'name=\"(.*?)\"\\r\\n\\r\\n(.*?)\\r\\n'
                matches = re.findall(pattern, data_result_list[0])
                for match in matches:
                    data[match[0]] = match[1]
                print(data)
        elif "--data-raw '" in curl_result:
            # 这个是表单传单或者json传参
            # print("需要处理表单传参和json传参")
            data_re_expression = re.compile("--data-raw '(.*?)'", re.S)
            data_result_list = re.findall(data_re_expression, curl_result)
            try:
                # 如果是JSON字符串{}或者[]直接进行转化成字典或者列表
                data = json.loads(data_result_list[0])
                print("我拿到了data", data, type(data))
            except:
                print(data_result_list[0])
                data_str = unquote(data_result_list[0])
                key_vale_str_list = (data_str.split("&") if "&" in data_str else None) if data_str else None
                print(key_vale_str_list)
                if key_vale_str_list:
                    for item in key_vale_str_list:
                        key = item.split("=")[0] if "=" in item else None
                        value = item.split("=")[1] if "=" in item else None
                        print(key, value)
                        if key:
                            if data.get(key) and isinstance(data.get(key), str):
                                # 如果key重复，则将value改成列表
                                source_value = data.get(key)
                                data[key] = []
                                data[key].append(source_value)
                                data[key].append(value)
                            elif data.get(key) and isinstance(data.get(key), list):
                                data[key].append(value)
                            else:
                                data[key] = value

        if not data:
            data = None
        if not params:
            params = None
        return path_result, step_name, method, params, data, headers

    def curl_to_yaml(self):
        # yaml用例模板数据
        yaml_case_template = {
            "suite_name": "场景名称_不改的人是pig",
            "suite_desc": "场景描述信息_不改的人是pig",
            "variables": None,
            "test_steps": []
        }
        # 处理是生成suite对象还是生成step列表
        return_suite_yaml = yaml_case_template
        return_steps_yaml = []
        # 循环处理批量curl请求
        step_name_dict = {}

        print(self.curl_data)
        curl_count = self.curl_data.count("curl")
        if curl_count >= 1:
            curl_list = self.curl_data.split("curl")[1:]
            print(curl_list)
            for curl_result in curl_list:
                step_template = {
                    "step_name": "步骤名称_不改的人是pig",
                    "step_desc": "步骤描述信息_不改的人是pig",
                    "wait_time": 0.0,
                    "request": {
                        "path": None,
                        "method": None,
                        "headers": None,
                        "params": None,
                        "data": None,
                        "files":
                            {
                                "file": None,
                            }
                    },
                    "sql_data": None,
                    "downloads": None,
                    "extract": None,
                    "checker": {
                        "code": 200,
                        "json": None,
                        "re": None
                    }
                }

                path, step_name, method, params, data, headers = self.handle_curl_2_yaml_case(
                    curl_result)

                step_template["step_name"] = step_name
                step_template["request"]["headers"] = headers
                step_template["request"]["method"] = method
                step_template["request"]["path"] = path
                step_template["request"]["params"] = params
                step_template["request"]["data"] = data
                # 组装yaml_case_template中的数据
                return_suite_yaml["test_steps"].append(step_template)
                return_steps_yaml.append(step_template)
            return return_suite_yaml, return_steps_yaml

        else:
            print("没有curl请求")


def business_curl_to_yaml(action, source_textarea_name, result_textarea_name):
    curl_data = unquote(pin[source_textarea_name])
    case_convert = CaseConvert(curl_data)
    test_case_suite_json, test_case_steps_json = case_convert.curl_to_yaml()
    if action == "suite":
        pin_update(result_textarea_name, value=yaml.round_trip_dump(test_case_suite_json))
    if action == "steps":
        pin_update(result_textarea_name, value=yaml.round_trip_dump(test_case_steps_json))
    if action == "download":
        if not curl_data:
            toast("请先输入curl,再下载测试用例")
            return
        data = yaml.round_trip_dump(test_case_suite_json, encoding="utf-8")
        return data


def html_curl_2_yaml():
    """
    用例转化

    :return:
    """
    show_menus()
    put_tabs(
        [
            {
                "title": "curl2yaml",
                "content": [
                    put_text("tips: 用例转化过程中出现参数异常情况请联系: 胡浩浩").style(
                        title_style),
                    put_html(
                        "<h4>复制curl请求: 打开chrome浏览器  -->  F12-->  选中请求  -->  copy  -->  Copy as cURL(bash)</h4>").style(
                        title_style),

                    put_row(
                        [
                            put_button("生成suite用例",
                                       onclick=lambda: business_curl_to_yaml("suite", "curl_request", "curl_result"),
                                       small=True),
                            None,
                            put_button("生成step用例",
                                       onclick=lambda: business_curl_to_yaml("steps", "curl_request", "curl_result"),
                                       small=True),
                            None,
                            put_button("下载测试用例",
                                       onclick=lambda: download('test_case_%s.yml' % str(int(time.time())),
                                                                business_curl_to_yaml("download", "curl_request",
                                                                                      "curl_result")), small=True)
                        ], size="14% 4% 14% 20% 10%"
                    ),
                    put_row(
                        [
                            put_textarea("curl_request", rows=38, code={
                                "mode": "js",
                                'theme': 'darcula'
                            }),
                            None,
                            put_textarea("curl_result", rows=38, code={
                                "mode": "yaml",
                                'theme': 'darcula'
                            }),
                        ], size="800px 4% 800px"
                    ),

                ],
            }
        ], scope="data_list"
    )
